package com.itdct.onflow.system.common.extend

import cn.hutool.core.util.ReflectUtil
import com.itdct.onflow.core.annotation.Dict
import com.itdct.onflow.core.extend.logWarn
import com.itdct.onflow.core.vo.BaseDetailVo
import com.itdct.onflow.system.common.exception.DictException
import com.itdct.onflow.system.dict.global.DictLock
import com.itdct.onflow.system.dict.global.DictMapGlobal


/**
 * @author Zhouwx
 * @date 2024/5/30 11:48:23
 * @version 1.0
 * @description
 */
fun <T> List<T>.dict(): List<T> {
    if (this.isEmpty()) {
        return this
    }

    if (!DictMapGlobal.enable) {
        logWarn("字典功能未启用")
        return this
    }

    val entity = this[0]
    entity?.also {
        // INFO: Zhouwx: 2024/5/30 筛选带有Dict注解的字段
        val fieldList = ReflectUtil.getFields(it::class.java).filter {
            val dict = it.getAnnotation(Dict::class.java)
            dict != null && dict.code.isNotBlank()
        }

        if (fieldList.isEmpty()) {
            return this
        }

        for (any in this) {
            any?.also {
                val clazz = it::class.java
                for (field in fieldList) {
                    field.isAccessible = true
                    val codeValue = field.get(it) ?: continue
                    val annotation = field.getAnnotation(Dict::class.java)
                    val parentCode = annotation.code
                    // INFO: Zhouwx: 2024/5/30 code由两部分组成，注解上的code和对应的字段的值
                    val findCode = "${parentCode}/${codeValue}"
                    // INFO: Zhouwx: 2024/5/30 找不到对应字典还是取原来的code值
                    var name = DictMapGlobal.dictCodeNameMap[findCode]
                    if (name == null) {
                        // INFO: Zhouwx: 2025/9/5 如果拿不到对应的值，首先想到是不是字典在更新
                        var retryTimes = 0
                        if (DictLock.lock.isLocked) {
                            // INFO: Zhouwx: 2025/9/5 如果字典在更新中，则等待字典更新完成
                            while (true) {
                                Thread.sleep(200)
                                // INFO: Zhouwx: 2025/9/5 等待后判断字典是否更新完成
                                if (DictLock.lock.isLocked) {
                                    // INFO: Zhouwx: 2025/9/5 如果还在等待，则继续重试
                                    retryTimes++
                                    if (retryTimes > 10) {
                                        throw DictException(findCode, "字典加载失败，请稍后再试")
                                    }
                                } else {
                                    name = DictMapGlobal.dictCodeNameMap[findCode]
                                    if (name == null) {
                                        // INFO: Zhouwx: 2025/9/5 如果取不到值，则抛出异常
                                        throw DictException(findCode, "无法加载到对应值")
                                    }
                                    break
                                }
                            }
                        } else {
                            // INFO: Zhouwx: 2025/9/5 没有加锁，说明取不到对应值了
                            Thread.sleep(50)
                            name = DictMapGlobal.dictCodeNameMap[findCode]
                            if (name == null) {
                                // INFO: Zhouwx: 2025/9/5 重试后依然无法加载到值，说明字典该值是缺失的
                                throw DictException(findCode, "无法加载到对应值")
                            }
                        }
                    }
                    if (annotation.replace) {
                        // INFO: Zhouwx: 2024/5/30 直接替换原来的值
                        field.set(it, name)
                    } else {
                        // INFO: Zhouwx: 2024/5/30 对指定字段赋值
                        if (annotation.field.isBlank()) {
                            // INFO: Zhouwx: 2024/5/30 直接替换原来的值
                            field.set(it, name)
                        } else {
                            try {
                                val theField = clazz.getDeclaredField(annotation.field)
                                theField.isAccessible = true
                                theField.set(it, name.toString())
                            } catch (e: Exception) {
                                logWarn("无法找到字段：${annotation.field}")
                            }
                        }
                    }
                }
            }
        }
    }
    return this
}

fun <T : BaseDetailVo> T.dict(): T {
    // INFO: Zhouwx: 2024/5/30 筛选带有Dict注解的字段
    val fieldList = ReflectUtil.getFields(this::class.java).filter {
        val dict = it.getAnnotation(Dict::class.java)
        dict != null && dict.code.isNotBlank()
    }

    if (fieldList.isEmpty()) {
        return this
    }

    val clazz = this::class.java
    for (field in fieldList) {
        field.isAccessible = true
        val codeValue = field.get(this) ?: continue
        val annotation = field.getAnnotation(Dict::class.java)
        val parentCode = annotation.code
        // INFO: Zhouwx: 2024/5/30 code由两部分组成，注解上的code和对应的字段的值
        val findCode = "${parentCode}/${codeValue}"
        // INFO: Zhouwx: 2024/5/30 找不到对应字典还是取原来的code值
        val name = DictMapGlobal.dictCodeNameMap[findCode] ?: codeValue
        if (annotation.replace) {
            // INFO: Zhouwx: 2024/5/30 直接替换原来的值
            field.set(this, name)
        } else {
            // INFO: Zhouwx: 2024/5/30 对指定字段赋值
            if (annotation.field.isBlank()) {
                // INFO: Zhouwx: 2024/5/30 直接替换原来的值
                field.set(this, name)
            } else {
                try {
                    val theField = clazz.getDeclaredField(annotation.field)
                    theField.isAccessible = true
                    theField.set(this, name.toString())
                } catch (e: Exception) {
                    logWarn("无法找到字段：${annotation.field}")
                }
            }
        }
    }
    return this
}